package org.znxs.znxsframe.bizmq;

import cn.hutool.core.util.StrUtil;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import org.znxs.znxsframe.common.ErrorCode;
import org.znxs.znxsframe.constant.BIConstant;
import org.znxs.znxsframe.constant.MQConstant;
import org.znxs.znxsframe.exception.BusinessException;
import org.znxs.znxsframe.manager.AIManager;
import org.znxs.znxsframe.model.entity.Chart;
import org.znxs.znxsframe.services.ChartService;
import org.znxs.znxsframe.utils.BIStrUtils;

import javax.annotation.Resource;


/**
 * 消息消费者  内部根据具体代码进行具体实现
 */
@Component
@Slf4j
public class BIMessageConsumer {

    @Resource
    private ChartService chartService;

    @Resource
    private AIManager aiManager;

    // 指定程序监听的消息队列和确认机制
    @SneakyThrows
    @RabbitListener(queues = {MQConstant.QUEUE_NAME}, ackMode = "MANUAL")
    public void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        log.info("receiveMessage message = {}", message);
        // 处理业务消息
        handleGenChart(channel, message, deliveryTag);
        channel.basicAck(deliveryTag, false);
    }

    @SneakyThrows
    private void handleGenChart(Channel channel, String message, long deliveryTag) {
        // 非空校验
        if (StrUtil.isBlank(message)) {
            // 拒绝消息     【1】 消息tag标识   【2】 拒绝消息      【3】 是否返回到队列中
            channel.basicNack(deliveryTag, false, false);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "接受消息为空");
        }
        // 根据id查询chart
        Chart chart = chartService.getById(Long.valueOf(message));
        if (chart == null) {
            // 拒绝消息     【1】 消息tag标识   【2】 拒绝消息      【3】 是否返回到队列中
            channel.basicNack(deliveryTag, false, false);
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "图表为空");
        }
        // 获取ai 生成数据
        StringBuilder userInput = new StringBuilder();
        userInput.append("分析目标:").append(chart.getGoal()).append("\n");
        userInput.append("图标类型：").append(chart.getChartType()).append("\n");
        userInput.append("数据:").append(chart.getChartData()).append("\n");


        // 修改图表状态为"执行中"。等执行成功后，修改为"已完成"  保存执行结果；执行失败后，状态修改为："失败"，记录任务失败信息
        // 修改状态为执行中
        boolean result = chartService.handleUpdateChartStatus(chart.getId(), "running");
        if (!result) {
            channel.basicNack(deliveryTag, false, false);
            chartService.handleUpdateChartStatusError(chart.getId(), "更新图表状态失败");
            return;
        }

        // 调用 ai模型管理器 进行提问
        String aiResult;
        try {
            System.out.println(userInput);
            GenerationResult generationResult = aiManager.callWithMessage(BIConstant.PRESET, userInput.toString());
            aiResult = generationResult.getOutput().getChoices().get(0).getMessage().getContent();
        } catch (Exception e) {
            channel.basicNack(deliveryTag, false, false);
            chartService.handleUpdateChartStatusError(chart.getId(), "ai 生成错误");
            return;
        }

        // 提取ai回答的内容信息
        // 提取图表代码
        String genChart;
        {
            // 正则表达式，匹配```包裹的内容
            String regex = "《(.*?)》";
            try {
                genChart = BIStrUtils.subStrByRegex(regex, aiResult, 5);
                System.out.println("【正则表达提取后数据】【】"+genChart);
            } catch (Exception e) {
                channel.basicNack(deliveryTag, false, false);
                chartService.handleUpdateChartStatusError(chart.getId(), "匹配正则失败");
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "匹配正则失败");
            }
        }
        // 提取图表分析结果
        String genResult;
        {
            // 正则表达式，匹配【】包裹的内容
            String regex = "【(.*?)】";
            try {
                genResult = BIStrUtils.subStrByRegex(regex, aiResult, 0);
            } catch (Exception e) {
                channel.basicNack(deliveryTag, false, false);
                chartService.handleUpdateChartStatusError(chart.getId(), "匹配正则失败");
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "匹配正则失败");
            }
        }

        // ai 生成之后 保存数据
        Chart finishGenChart = new Chart();
        finishGenChart.setId(chart.getId());
        finishGenChart.setGenChart("{" + genChart);
        finishGenChart.setGenResult(genResult);
        try {
            chartService.updateById(finishGenChart);
        } catch (Exception e) {
            channel.basicNack(deliveryTag, false, false);
            chartService.handleUpdateChartStatusError(chart.getId(), "ai 生成数据插入失败");
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "ai 生成数据插入失败");
        }

        // 修改状态为已完成
        boolean result2 = chartService.handleUpdateChartStatus(chart.getId(), "succeed");
        if (!result2) {
            channel.basicNack(deliveryTag, false, false);
            chartService.handleUpdateChartStatusError(chart.getId(), "更新图表状态失败");
        }

    }

}
